package com.aliang.clickhouseautoconfig.pool;

import java.sql.Connection;
import java.sql.DriverManager;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ClickhousePoolImpl implements ClickhousePool {

    //todo 初始化连接数
    private LinkedBlockingQueue<Connection> coreConnect;

    //todo 最大创建连接数
    private LinkedBlockingQueue<Connection> maxConnect;

    //todo 正在使用的连接
    private LinkedBlockingQueue<Connection> busyConnect;

    private int coreSize;

    private int maxSize;

    private String url;

    private String driverClass;

    private String name;

    private String password;

    Lock lock = new ReentrantLock();

    @Override
    public void init() {
        Connection connection = null;
        try{
            //todo core 初始化
            coreConnect = new LinkedBlockingQueue<>(getCoreSize());
            maxConnect = new LinkedBlockingQueue<>(getMaxSize() - getCoreSize());
            busyConnect = new LinkedBlockingQueue<>(getMaxSize());
            for (int i =1; i <= coreSize; i++){
                if (i > coreSize){
                    continue;
                }
                connection = buildConnection();
                coreConnect.add(connection);
            }
            for (int j =1; j <= getMaxSize() - getCoreSize(); j++){
                if (j >getMaxSize() - getCoreSize()){
                    continue;
                }
                connection = buildConnection();
                maxConnect.add(connection);
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private Connection buildConnection() throws Exception{
        final Class<?> aClass = Class.forName(driverClass);
        Connection connection = DriverManager.getConnection(url, name, password);
        return connection;
    }

    @Override
    public Connection getConnection() {

        Connection poll = coreConnect.poll();
        lock.lock();
        try{
            if (null == poll){
                if (maxConnect.poll() == null){
                    poll = coreConnect.take();
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
        busyConnect.add(poll);
        return poll;
    }

    @Override
    public void releaseConnection() {
        final Connection poll = busyConnect.poll();
        if (null != poll){
            if (coreConnect.offer(poll)){
                return;
            }else {
                maxConnect.offer(poll);
                return;
            }
        }
    }

    public int getCoreSize() {
        return coreSize;
    }

    public void setCoreSize(int coreSize) {
        this.coreSize = coreSize;
    }

    public int getMaxSize() {
        return maxSize;
    }

    public void setMaxSize(int maxSize) {
        this.maxSize = maxSize;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getDriverClass() {
        return driverClass;
    }

    public void setDriverClass(String driverClass) {
        this.driverClass = driverClass;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}
